iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 6
8
DevOps

Kubernetes 30天學習筆記系列 第 6 篇

[Day 6] 實際環境運行的 Kubernetes - Node & Architecture Overview

  • 分享至 

  • xImage
  •  

前言

其實 Kubernetes 官方的文件,已經將 Kubernetes 上的每個元件的功能都已解釋的非常清楚。官網上現在也提供 互動式學習的教學,對於有心想學習Kubernetes讀者,這兩者都是非常有幫助的資源。然而筆者在自學的過程中,發覺若是能先暸解 Kubernetes 內部如何運作,對於之後學習 Kubernetes 的基礎元件是非常有幫助的,因此今天的學習筆記,除了介紹 Node 元件 以外,也會從一個概觀的角度去介紹 Kubernetes 的內部運作。

今日內容如下:

  • 介紹 Node 是什麼
  • 概觀 Kubernetes 的內部運作

Node 是什麼

在 Kubernetes 中,Node 通常是指實體機、虛擬機。一個Node,可以是指 AWS的一台EC2 或 GCP上的一台computer engine ,也可以是你的筆電,甚至是一台 Raspberry Pi。只要他們上面裝有 Docker Engine ,足以跑起 Pod,就可以被加入 Kubernetes Cluster。

將 Node 加到 Kubernetes 中之後,Kubernetes 會建立一個Node 物件,並進行一連串檢查,包含網路連線,Pod 是否能被正常啟動等,若都通過則會將該Node物件的狀態設為 Ready,若是無法通過則會顯示 Not Ready

若還是記得 第二天在本機端架好的 minikube,輸入 kubectl get nodes 指令,就可以發現 minikube 已在其中

kubectl-get-nodes

當然也可以使用 kubectl describe nodes 取得該 Node 的詳細資料,以下以 minikube 為例 (更多 log 可參考 kubectl-describe-node-minikube),

$ kubectl describe nodes minikub

由於我們目前是在本機端操作,只有一個 Node。在 未來的學習筆記 中,也會介紹到如何利用第三方套件 kops 在 AWS 上打造多台機器的 Kubernetes Cluster

用 Kubernetes 管理 Nodes 的好處

過去是一台 Node 指運行可能只運行一個應用服務(application),若是該應用服務(application) 只使用 I/O 資源,免不了 Node 上閒置 memory 的浪費;若是為了避免閒置資源,而將多個服務同時運行在同一台 Node 上,運維人員還需隨時掌控目前各個應用服務使用資源狀況,避免資源不足情形。而在 Kubernetes 上,當我們將 Node 都加到 Kubernetes Cluster 後,系統會根據目前 Pod 的設定檔去決定要部署在哪個 Node 上。在未來讀書筆記 [Day 27] 如何限制每個服務資源 - Resource Quotas 也會分享這部分。

概觀 Kubernetes 的內部運作

在實際場景應用上,Kubernetes 是會由多台 Node 組成,今天將藉由底下這張 簡化的 Kubernetes 系統架構圖 講解 Kubernetes 的內部是如何溝通(圖中並無 Master Node):

Master Node 主要用來管理與調度Kubernetes Cluster 中所有物件的狀態,讀者只需有有該概念即可,在 [Day 26] 介紹Kubernetes調度中心 - Master Node 會更詳細介紹。

kubernetes-orverview

  • 該圖中的 Kubernetes Cluster 有 N 個 Nodes,Node 1, Node 2, ... Node N

  • 每個 Node 都必須跑起 Container Engine 以便於運行 Pods。
    而在30天教學筆記中使用的是 Docker Engine。

  • 圖中,一個橘色框分別代表一個 Pod ,而 Pod 中綠色的空心方型則代表一個container。以 Pod 3 與 Pod 5 為例,這兩個 Pod 分別只運行一個 container;而在 Pod 1 中則運行三個 containers。

  • 圖中每個 Node 都有屬於它自己的 iptables,iptables 是 Linux 上的防火牆(firewall),不只限制哪些連線可以連進來,也會管理網路連線,決定收到的 request 要交給哪個 Pod。

在對這張架構圖有基本認識之後,我們會藉由這張圖來解釋每個 Kubernetes 的內部是如何溝通:

1. 同一個 Pod 中的 containers,可以透過 Pod 內部的網路直接溝通

由於每個Pod中有自己的網路。所以同一個Pod中的containers之間可以透過**<localhost:port_num>**互相溝通。而這樣無需透過外網的性質,讓我們可以將性質相近的服務放在同一個Pod裡,好比一個後端API service,與一個後端認證service,可以放在同一個pod裡互相溝通。

2. Kubelet & kube-proxy

在每個 Node物件 中都會有,kubelet與kube-proxy

  • kubelet
    kubelet相當於 node agent,用於管理該 Node 上的所有 pods以及與 master node 即時溝通。

  • kube-proxy
    kube-prox y則是會將目前該 Node 上所有 Pods 的資訊傳給 iptables,讓 iptables 即時獲得在該 Node 上所有 Pod 的最新狀態。好比當一個 Pod物件 被建立時,kube-proxy 會通知 iptables,以確保該 Pod 可以被 Kubernetes Cluster 中的其他物件存取。

  • Load balancing
    在實際場景中,收到外部傳來的 requests 都會先交由 Load balancer 處理,再由 Load balancer 決定要將 request 給哪個 Node ,通常 Load balancer 都是由 Node 供應商提供,好比 AWS 的 ELB,或是自己架設 Nginx 或 HAProxy 等專門做負載平衡的服務。

3. 所以,當我們創建一個新的 Pod 後,收到使用者發送的 request 時,ks8 內部會發生什麼事呢

  • 首先,kubelet 會先收到 master node 指令,創建一個 Pod。創建好後,kube-proxy 會去告知 iptables,目前該 Pod 可用。

  • 當使用者透過 網路(internet) 發送 requests 時,requests 會先送到 Load Balancer,由 Load Balancer 決定要把request交給哪個 Node,這時收到 requests的 Node 會經由 iptables 決定要送給哪個 Pod 。

  • 但如果收到request的 Node 恰好沒有相對應可以處理 request Pod 的話,原本收到 request 的 Node 會透過 iptables 把 request 轉給其他有可以處理這個 request 的 Node 。

總結

在 Kubernetes 的 Github 上對 Kubernetes 的架構做了詳細的介紹,對於 Kubernetes 內部運作有興趣的讀者不妨看一看。明天的學習筆記,將介紹 Kubernetes 的另一個重要的核心元件 Replication Controller

Q&A

依舊歡迎大家給予建議與討論,如果能按個讚給些鼓勵也是很開心唷 : )

參考連結


上一篇
[Day 5] 在 Minikube 上跑起你的 Docker Containers - Pod & kubectl 常用指令
下一篇
[Day 7] 如何擴展我的pods?! - Replication Controller
系列文
Kubernetes 30天學習筆記 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
herb123456
iT邦新手 5 級 ‧ 2018-01-07 23:12:40

想請問最後的

但如果收到request的 Node 恰好沒有相對應可以處理 request Pod 的話,原本收到 request 的 Node 會透過 iptables 把 request 轉給其他有可以處理這個 request 的 Node 。

這個 Node 要怎麼知道 收到的 request 可以轉發給哪個node?

看更多先前的回應...收起先前的回應...
zxcvbnius iT邦新手 5 級 ‧ 2018-01-08 00:32:06 檢舉

這裡我寫的不太好,事實上所有請求(request)要最終指向哪個 Pod 都是 kube-proxy 與 iptables決定的。

解釋之前,我們可能要先知道 Kubernetes 中的 Endpoints

Endpoint 是什麼

每次新的 Service 建立,Kubernetes 也會創建一個 Endpints 物件,用來儲存這個新建立的 Server 與相對應的 Pods 的關係。好比有一個 Service

{
  “name”: “nginx”,
  “endpoints”: [“10.0.0.1”, “10.0.0.2”]
}

代表這個名為 nginx 的 service,後面有兩個相對應的 Pods,cluster ip 分別是 “10.0.0.1” 與 “10.0.0.2”

而 Endpoint 也會跟隨 Pod 目前的狀況動態改變紀錄的值,確保每次 service 傳進來的請求都能找到相對應的 Pod。

若是有興趣,可以在每次創建好一個 service 物件後,透過 kubectl describe 或 kubectl get ep指令,都可以看到該 service 對應的 endpoint 的資料。或是也可以參考 官網提供的 kubectl describe svc 範例

kube-proxy

事實上,每個 Node 上都有自己的kube-proxy 與 iptables,一旦有新的 Service 建立或是改動後,每個 kube-proxy 都會針對該 Service 設置相同的轉送規則,並將這些 rule 存在 iptables。(可以說是每個 Node 上的 kube-proxy 都會知道所有 service 的狀態)

接收service的存取請求後

Kube-proxy 會依據 endpoint 紀錄的 ip 清單,透過 Round Robin 的方式,在本機端的記憶體尋找是否存在相對應 ip ,如果有就指向相對應的 Pod 物件(代表 Pod 在 Node 上)。如果沒有,則會選擇 endpoint 中的一組 ip,將存取請求指向該 ip,由該 ip 相對應的物件處理(將 request 送到另外一個 Node)。

非常感謝您的詳細回應,但我看過兩三次後,覺得應該沒有回答到我的疑問,或是我還不太能理解其中的運作原理。

我先釐清一下其他問題

  1. kube-proxy 與 iptables 是否都在 node 內?
  2. 若是在node內,所以代表 request 已經丟給了 node 才由 kube-proxy 與 iptables 決定丟給某個pod?
  3. 這時候會發生沒有pod可以處理的情況嗎?(那kubernetes master又是怎麼決定丟給這個node的?)
  4. 如果有對應的pod比較沒問題,應該就是由node內的iptables的nat機制轉送給相應的pod
  5. 如果發生沒有pod可以處理的情況,node to node 的機制又是誰、用什麼方式決定的?
  6. 在一個 cluster 內一定不止一個或兩個 node,應該不可能用輪詢的方式傳遞給其他node吧?
zxcvbnius iT邦新手 5 級 ‧ 2018-01-08 07:43:40 檢舉

hi @herb123456,

  • 問題 1, 2
    沒錯,每個 Node 上都有自己的kube-proxy 與 iptables,所有請求最終要指向哪個 Pod 都是 kube-proxy 與 iptables決定的。
  • 問題 3, 4, 5
    如果Service 後面沒有 Pod 的話,請求會 hang/timeout
  • 問題 6
    其實上述有提到,kube-proxy 會依據 endpoint 紀錄的 ip 清單,透過 Round Robin 的方式,在本機端的記憶體尋找是否存在相對應 ip ,如果有就指向相對應的 Pod 物件(代表 Pod 在 Node 上)。如果沒有,則會選擇 endpoint 中的一組 ip,將存取請求指向該 ip,由該 ip 相對應的物件處理(將 request 轉送到另外一個 Node)。也就是,當 Node 收到 request 後,Node 上的 kube-proxy 會決定要送到哪個 Pod ip address,再由 iptables 轉發。

感謝您的熱心回應

大部分的疑問都了解了

但我還有個疑問就是你最後提到的

如果沒有,則會選擇 endpoint 中的一組 ip,將存取請求指向該 ip,由該 ip 相對應的物件處理(將 request 轉送到另外一個 Node)。

此份 endpoint 清單,是記錄誰的ip?

依據您之前的回應

kube-proxy 會依據 endpoint 紀錄的 ip 清單,透過 Round Robin 的方式,在本機端的記憶體尋找是否存在相對應 ip ,如果有就指向相對應的 Pod 物件(代表 Pod 在 Node 上)

這份 ip 清單是否為 pod 的 ip 清單?抑或是還有紀錄其他 node 的清單呢?

若是還有紀錄其他node的清單,但這時候又該怎麼知道要轉給哪個node呢?

總不可能隨機挑選一個node,然後很不幸的要在最後一個node才有pod可以處理這個request?

我其實一直對會把這個request轉給其他node有很大的問號啊。

zxcvbnius iT邦新手 5 級 ‧ 2018-01-09 20:43:04 檢舉

Hi @herb12346,

1/ 沒錯 endpoint 會記錄 pod ip list。之後不妨可以試試建立一個 service 與一個相對應的 pod,再用 kubectl describe 去查看 service 的資料,會發現endpoint的欄位後面記錄的會是該對應pod的 Cluster IP

2/接續我們上述以及前面提到的, kube-proxy 會從 endpoint 找到 pod IP list ,會用 Round Robin 的方式去找對應的 pod 。每個 Node 都有自己的 kube-proxy ,如果接收到請求的 kube-proxy 發現在同一個 node 中有相對應的 pod 物件,就會將流量導到該 pod ;然而,若是這個 kube-proxy 選擇的 pod 部署在其他 node 上,則會透過 iptables 將這個流量導到有對應的 node 上。在文中提到的 把 request 轉給其他有可以處理這個 request 的 Node 便是這個意思,不是隨機挑選一個 Node 而是由 kube-proxy 決定把流量要給那個 node 。

也很開心有人提問呢,希望這樣有解答你的疑惑!

原來如此啊

所以每一份清單都會紀錄其他node上的pod嗎?

也就是這份清單是每個node都會相同嗎?

zxcvbnius iT邦新手 5 級 ‧ 2018-01-13 15:00:26 檢舉

理論上是喔~

我要留言

立即登入留言